#include <reg51.h>

typedef unsigned char uint8_t;

#define SEGMENT_PORT P0
#define PLACE_PORT P1
#define KEYBORD_PORT P2

#define PLACE_COUNT 4
#define CLICK_WAIT 10

#define DELAY(t)                      \
    do {                              \
        uint8_t j, __t = (t);         \
        while (__t--)                 \
            for (j = 0; j < 113; ++j) \
                ;                     \
    } while (0)

uint8_t click_count = 0;
uint8_t current_key = 0xff;

uint8_t segment_code[] = {
    0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
};

uint8_t place_code[PLACE_COUNT] = {0xfe, 0xfd, 0xfb, 0xf7};

uint8_t buffer[PLACE_COUNT] = {1, 2, 3, 4};

void timer_init() {
    TMOD = 0x01;
    TL0 = 0x00;
    TH0 = 0xb8;
    IE = 0X82;
    TR0 = 1;
}

int main() {
    timer_init();
    while (1)
        ;
}

void display() {
    uint8_t i;
    for (i = 0; i < PLACE_COUNT; ++i) {
        SEGMENT_PORT = segment_code[buffer[i]];
        PLACE_PORT = place_code[i];
        DELAY(2);
        PLACE_PORT |= 0x0f;
    }
}

void refresh_buffer(uint8_t key) {
    uint8_t base, i;
    for (base = 0x01, i = 0; i < PLACE_COUNT; ++i) {
        if ((key & (base << i)) && ++buffer[i] > 9) buffer[i] = 0;
    }
}

void T0Isr() interrupt {
    uint8_t key = KEYBORD_PORT;
    if (key == current_key) {
        if (++click_count > CLICK_WAIT) {
            click_count = 0;
            current_key = 0xff;
            refresh_buffer(~key);
        }
    } else {
        current_key = key;
    }

    display();
    TL0 = 0x00;
    TH0 = 0xb8;
}